'''
Created on Jul 21, 2013

@author: Cihat Basol
'''


import logging
import os
import time
import zipfile

from dexen.common.constants import ENV_DB_IP, ENV_DB_PORT
from dexen.common.db import FileManager
from dexen.node import env_mgr


_last_update_time = 0


class TaskExecutor(object):
    def __init__(self, execution, result_queue, worker_name, db_client):
        super(TaskExecutor, self).__init__()
        self.execution = execution
        self.task = execution.task
        self.result_queue = result_queue
        self.worker_name = worker_name
        self.db_client = db_client
        self.logger = logging.getLogger(__name__+"."+self.__class__.__name__+
                                        "."+self.worker_name)
        self.file_mgr = FileManager(db_client, execution.user_name)

    def _extract_zip(self, f):
        z = zipfile.ZipFile(f, mode="r")
        z.extractall()

    def _prepare_context(self):
        global _last_update_time
        rootdir = env_mgr.get_job_dir(self.worker_name,
                                      self.execution.user_name,
                                      self.execution.job_name, create=True)
        self.last_dir = os.getcwd()
        os.chdir(rootdir)
        self.logger.debug("The rootdir is: %s", rootdir)
        file_names = self.file_mgr.get_recent_files(self.execution.job_name,
                                                    _last_update_time)
        _last_update_time = time.time()
        for file_name in file_names:
            self.logger.info("Retrieving file %s", file_name)
            remote_file = self.file_mgr.get_file(self.execution.job_name,
                                                 file_name)
            if file_name.endswith(".zip"):
                self._extract_zip(remote_file)
            else:
                with open(file_name, "wb") as f:
                    f.write(remote_file.read())
                remote_file.close()

    def _restore_context(self):
        os.chdir(self.last_dir)

    def _setup_env(self):
        env = {}
        env[ENV_DB_IP] = str(self.db_client.host)
        env[ENV_DB_PORT] = str(self.db_client.port)
        for key, value in os.environ.iteritems():
            if key not in env:
                env[key] = value
        return env

    def execute(self):
        self.logger.info("executing %s", self.task.name)
        self._prepare_context()
        env = self._setup_env()
        exec_result = self.execution.execute(env)
        self._restore_context()
        self.logger.info("executing %s is done", self.task.name)
        self.result_queue.put(exec_result)


